/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package problema_puente;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 *
 * @author Gaby
 */
public class CrucePuente {
//clase que permite generar numeros aleatorios
    static Random r = new Random();
    //variable entera que almacena el tiempo total que realizan los elementos para cruzar de un extremo a otro
    static int tiempoTotal;
    //variable objeto que almacena un elemento puede ser A,B,C,D
    static String objAux;
    //variable cadena que almacena la secuencia del recorrido de los elementos
    static String secuencia;

    /**
     * Metodo elementoAleatorio, permite elegir de forma aleatoria un de los elementos
     * que se encuentran dentro de la lista enviada como parámetro.
     * @param l : lista de tipo List que contiene todos los elementos que participan en el cruce del puente
     * @return Retorna el elemento de tipo String escogido de forma aleatoria
     */
    public static String elementoAleatorio(LinkedList<String> l) {
        objAux = null;
        int posAleat;
        posAleat = Math.abs(r.nextInt()) % l.size();
        objAux = l.get(posAleat);
        return objAux;
    }

    /**
     * Metodo menorTiempo, permite elegir el elemento de menor tiempo que se
     * encuentra alamcenado en una lista
     * @param l, lista de tipo LinkedList que contiene los elementos apartir de
     * los cuales se va a elegir el de menor tiempo
     * @param m, lista ordenada de tipo HashMap que tiene almacenado todos los
     * elementos(tipo String) con sus respectivos tiempos(tipo Integer).
     * @return, Retorna el elemento que tiene el menor tiempo
     */
    public static String menorTiempo(LinkedList<String> l, HashMap<String, Integer> m) {
        int tMenor = 0;
        for (int i = 1; i < l.size(); i++) {
            if (m.get(l.get(i)) < m.get(l.get(tMenor))) {
                tMenor = i;
            }
        }
        return l.get(tMenor);
    }

    /**
     * El metodo imprimir permite presentar en pantalla todos los lementos que contiene una lista
     * @param auxL es la Lista con los elementos que se desea presentar en pantalla
     */
    public static void imprimir(List auxL) {
        Iterator iter2 = auxL.iterator();
        while (iter2.hasNext()) {
            System.out.println(iter2.next());
        }
    }

    /**
     * Metodo solucion se encarga de pasar todos los elementos de una lista a otra
     * tomando en cuenta los tiempos de cada elemento
     * @param izquierda, es la lista origen, contiene todos los elementos que se
     * desea pasar a la lista destino
     * @param derecha, es la lista destino que inicialmente esta vacia
     * @param mapa, lista ordenada que contiene los elementos del problema con sus respectivos tiempo
     * @return retorna el tiempoTotal que ocupan todos los elementos en cruzar el puente
     * de izquierda a deracha
     */
    public static int solucion(LinkedList<String> izquierda, LinkedList<String> derecha, HashMap<String, Integer> mapa) {
        /**
         * variable de tipo String que alamacena cada una de los movimientos (cruce y regreso)
         * que se generan al pasar los elementos entre las dos listas
         */
        secuencia = " ";
        //variable de tipo entero que alamcena la suma de los tiempos parciales
        tiempoTotal = 0;
        //ciclo repetitivo que se se ejecuta mientras la lista de la izquierda tenga elementos
        while ((!izquierda.isEmpty())) {
            /**
             * Es necesario inicializar cada una de las variables, para evitar 
             * que la informacion de la iteracion anterior se mezcle con la
             * siguiente la variable tiempoParcial permite almacenar el mayor
             * tiempo empleado en cruzar el puente.
            */
            objAux = null;
            Integer tiempoParcial = 0;

            /**
             * ciclo que se ejecutara en dos ocaciones, esto controla que solo 
             * dos elementos de la izquierda pasen a la lista de la derecha
             */
            for (int i = 0; i < 2; i++) {
                //almacena en una variable auxiliar un elementos elegido de forma
                //aleatoria utilizando el metodo elementoAleatorio
                objAux = elementoAleatorio(izquierda);
                //las dos sentencias permiten realizar el moviento de cruce del puente
                //se agrega a la lista de la derecha el elemento objAux
                derecha.add(objAux);
                //se elimina de la lista de la izquierda el mismo elemento que fue agregado en la derecha objAux
                izquierda.remove(objAux);

                /**
                 * Condicionales que verifican cual es el mayor de los tiempos de cruce
                 * Primera condicion:cuando el tiempoParcial es 0, es verdadera
                 * cuando se trata del primer elemento que cruza
                 * Segunda condicion:compara el tiempo del 1er elemento en cruzar
                 * con el del 2do elemento
                */
                if (tiempoParcial == 0) {
                    tiempoParcial = mapa.get(objAux);
                } else if (mapa.get(objAux) > tiempoParcial) {
                    tiempoParcial = mapa.get(objAux);
                }
                //cada movimiento de los elementos en la etapa de cruce se alamcena en
                //la variable secuencia
                secuencia = secuencia + objAux;
            }
            //finalizada la etapa de cruce el tiempoParcial se agrega al tiempo total
            tiempoTotal = tiempoTotal + tiempoParcial;

            /**
             * Condicional que permite el regreso de un elemento a la lista origen
             * si ésta tiene elementos
             */
            if (!izquierda.isEmpty()) {
                //alacena en la variable auxiliar objAux el elemento de menor tiempo
                //que se obtiene al invocar el metodo menorTiempo
                objAux = menorTiempo(derecha, mapa);
                //estas dos sentencias realizar el movimiento de regreso de un elemento
                izquierda.add(objAux);
                derecha.remove(objAux);
                //el movimiento del elemento en la etapa de regreeso se alamcena en
                //la variable secuencia
                secuencia = secuencia + ", " + objAux + ", ";
                //finalizada la etapa de regreso el tiempo del elemento que regresa
                //se agrega al tiempo total. Fijese que los tiempos son requeridos
                //desde la estructa Mapa ingresada como parametro
                tiempoTotal = tiempoTotal + mapa.get(objAux);
            }
        }
       return tiempoTotal;
    }   
}
